package com.erp.erp_ui.warehouse.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.erp.enums.ContractTypeEnum;
import com.erp.enums.ModuleTypeEnum;
import com.erp.enums.OperationStatusEnum;
import com.erp.erp_entitys.money.rsp.PaymentStatistics1Rsp;
import com.erp.erp_entitys.warehouse.entity.*;
import com.erp.erp_entitys.warehouse.req.ImportCarryPlanReq;
import com.erp.erp_entitys.warehouse.req.ImportPurchaseReq;
import com.erp.erp_entitys.warehouse.req.OtherInStockPageListInfoReq;
import com.erp.erp_entitys.warehouse.req.sellOutStockStatistics1Req;
import com.erp.erp_entitys.warehouse.rsp.*;
import com.erp.erp_servers.warehouse.*;
import com.erp.erp_ui.money.req.OperationReq;
import com.erp.erp_ui.warehouse.enums.DataIsValidEnum;
import com.erp.erp_ui.warehouse.enums.DataSourceTitleEnum;
import com.erp.erp_ui.warehouse.req.*;
import com.erp.erp_ui.warehouse.vo.*;
import com.erp.utils.DateUtils;
import com.erp.utils.R;
import com.erp.utils.ResultStatusEnum;
import com.erp.utils.StringUtil;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName : OtherInStockService
 * @Description : 其它入库业务逻辑层
 * @Author : lst
 * @Date: 2021-03-24 18:35
 */
@Service
public class OtherInStockService {

    /**
     * 日志
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(OtherInStockService.class);

    /**
     * 其它入库主表接口
     */
    private final IOtherInStockService otherInStockService;

    /**
     * 其它入库明细接口
     */
    private final IOtherInStockDetailService otherInStockDetailService;

    /**
     * 库存接口
     */
    private final IStockService stockService;

    /**
     * 库存明细接口
     */
    private final IStockDetailService stockDetailService;

    /**
     * 附件接口
     */
    private final IAnnexService annexService;

    /**
     * 临时附件接口
     */
    private final ITempAnnexService tempAnnexService;

    @Autowired
    public OtherInStockService(IOtherInStockService otherInStockService,
                               IOtherInStockDetailService otherInStockDetailService,
                               IStockService stockService,
                               IStockDetailService stockDetailService,
                               IAnnexService annexService,
                               ITempAnnexService tempAnnexService) {
        this.otherInStockService = otherInStockService;
        this.otherInStockDetailService = otherInStockDetailService;
        this.stockService = stockService;
        this.stockDetailService = stockDetailService;
        this.annexService = annexService;
        this.tempAnnexService = tempAnnexService;
    }


    /**
     * 其它入库-首页-分页查询
     *
     * @param req 查询条件
     * @return 分页结果
     */
    public PageInfo<OtherInStockPageListVo> getListByPage(OtherInStockPageListInfoReq req) {
        if (StringUtils.isBlank(req.getOperationNo())) {
            return null;
        }
        //去除前后空格
        if(StringUtils.isNotEmpty(req.getInfo())){
            req.setInfo(req.getInfo().trim());
        }
        //调用接口获取查询结果
        List<OtherInStockEntity> otherOutStocks = otherInStockService.getListByPage(req);
        //获取分页信息
        PageInfo pageInfo = new PageInfo(otherOutStocks);
        //初始化回参集合
        List<OtherInStockPageListVo> pageVos = new ArrayList<>();
        if (CollectionUtils.isEmpty(otherOutStocks)) {
            pageInfo.setList(pageVos);
            return pageInfo;
        }
        for (OtherInStockEntity other : otherOutStocks) {
            OtherInStockPageListVo pageVo = new OtherInStockPageListVo();
            BeanUtils.copyProperties(other, pageVo);
            //日期转换
            pageVo.setCreateDate(DateUtils.format(other.getCreateDate()));
            //状态转换
            pageVo.setStatusStr(OperationStatusEnum.getDescById(other.getStatus()));

            pageVos.add(pageVo);
        }
        pageInfo.setList(pageVos);
        return pageInfo;
    }

    /**
     * 导采购主表信息
     *
     * @param req 查询参数
     * @return 采购主表信息
     */
    public PageInfo<ImportPurchaseVo> getImportPurchaseInfo(ImportPurchaseReq req) {
        //去掉前后空格
        if(StringUtils.isNotEmpty(req.getPurchaseOrderNo())){
            req.setPurchaseOrderNo(req.getPurchaseOrderNo().trim());
        }
        if(StringUtils.isNotEmpty(req.getProductNo())){
            req.setProductNo(req.getProductNo().trim());
        }
        if(StringUtils.isNotEmpty(req.getSpecNo())){
            req.setSpecNo(req.getSpecNo().trim());
        }
        if(StringUtils.isNotEmpty(req.getSupplierName())){
            req.setSupplierName(req.getSupplierName().trim());
        }

        List<ImportPurchaseRsp> purchaseInfo = otherInStockService.getImportPurchaseInfo(req);
        //获取分页信息
        PageInfo pageInfo = new PageInfo(purchaseInfo);
        //初始化回参集合
        List<ImportPurchaseVo> voList = new ArrayList<>();
        if (CollectionUtils.isEmpty(purchaseInfo)) {
            pageInfo.setList(voList);
            return pageInfo;
        }
        for (ImportPurchaseRsp purchase : purchaseInfo) {
            //初始化回参对象
            ImportPurchaseVo vo = new ImportPurchaseVo();
            //赋值
            BeanUtils.copyProperties(purchase, vo);
            //创建日期
            vo.setCreateTime(DateUtils.format(purchase.getCreateTime()));
            //交货日期
            vo.setDeliverDate(DateUtils.format(purchase.getDeliverDate()));

            voList.add(vo);
        }
        pageInfo.setList(voList);
        return pageInfo;
    }


    /**
     * 导入采购产品信息
     *
     * @param id 采购主键id
     * @return 采购产品信息
     */
    public List<ImportPurchaseProductVo> getImportPurchaseProduct(Integer id) {
        //根据采购主表id获取采购产品信息
        List<ImportPurchaseProductRsp> productList = otherInStockService.getImportPurchaseProduct(id);
        //初始化回参对象集合
        List<ImportPurchaseProductVo> voList = new ArrayList<>();
        if (CollectionUtils.isEmpty(productList)) {
            return voList;
        }
        for (ImportPurchaseProductRsp product : productList) {
            //如果该产品对应的配件未完全做完采购，则该产品不允许导入
            int count = otherInStockService.getUnPurchasePartsCount(product.getSalesContractNo());
            if(count > 0){
                //存在未做完采购的配件,该产品不允许导入
                continue;
            }
            //初始化回参对象
            ImportPurchaseProductVo vo = new ImportPurchaseProductVo();
            //赋值
            BeanUtils.copyProperties(product, vo);
            //成本单价
            BigDecimal productUnitPrice = product.getProductUnitPrice();
            //获取采购配件的平均价格
            BigDecimal partsPrice = otherInStockService.getPurchasePartsPrice(product.getPurchaseDetailId());
            //新的成本单价(成品成本+配件成本)
            BigDecimal newPrice = productUnitPrice.add(partsPrice);
            //设置新的成本单价
            vo.setProductUnitPrice(newPrice);

            //合同类型,默认其它入库
            vo.setContractType(ContractTypeEnum.OTHER_IN_STOCK.getId());
            //获取已被调用数量
            BigDecimal sum = getQuantityAlreadyOut(product.getProductCode(), product.getSpecificationCode(), product.getPurchaseNo());
            //产品总数
            BigDecimal totalQuantity = new BigDecimal("0");
            if (StringUtil.isNotEmpty(product.getTotalQuantity())) {
                totalQuantity = product.getTotalQuantity();
            }
            //剩余数量
            BigDecimal lastQuantity = totalQuantity.subtract(sum);
            vo.setReferenceQuantity(lastQuantity);
            //成本金额小计=成本单价*数量
            BigDecimal costAmount = newPrice.multiply(lastQuantity);
            vo.setCostAmount(costAmount);

            voList.add(vo);
        }

        return voList;
    }


    /**
     * 导出运计划信息
     *
     * @param req 查询参数
     * @return 出运计划信息
     */
    public PageInfo<ImportCarryPlanVo> getImportCarryPlan(ImportCarryPlanReq req) {
        //去除前后空格
        if(StringUtils.isNotEmpty(req.getShipmentNo())){
            req.setShipmentNo(req.getShipmentNo().trim());
        }
        List<ImportCarryPlanRsp> purchaseInfo = otherInStockService.getImportCarryPlan(req);
        //获取分页信息
        PageInfo pageInfo = new PageInfo(purchaseInfo);
        //初始化回参集合
        List<ImportCarryPlanVo> voList = new ArrayList<>();
        if (CollectionUtils.isEmpty(purchaseInfo)) {
            pageInfo.setList(voList);
            return pageInfo;
        }
        for (ImportCarryPlanRsp purchase : purchaseInfo) {
            //初始化回参对象
            ImportCarryPlanVo vo = new ImportCarryPlanVo();
            //赋值
            BeanUtils.copyProperties(purchase, vo);
            //创建日期
            vo.setCreateTime(DateUtils.format(purchase.getCreateTime()));
            //出运日期
            vo.setShipmentDate(DateUtils.format(purchase.getShipmentDate()));

            voList.add(vo);
        }
        pageInfo.setList(voList);
        return pageInfo;
    }

    /**
     * 导入出运计划产品信息
     *
     * @param id 出运计划主键id
     * @return 出运计划产品信息
     */
    public List<ImportCarryPlanProductVo> getImportCarryPlanProduct(Integer id) {
        //根据采购主表id获取采购产品信息
        List<ImportCarryPlanProductRsp> productList = otherInStockService.getImportCarryPlanProduct(id);
        //初始化回参对象集合
        List<ImportCarryPlanProductVo> voList = new ArrayList<>();
        if (CollectionUtils.isEmpty(productList)) {
            return voList;
        }
        for (ImportCarryPlanProductRsp product : productList) {
            //初始化回参对象
            ImportCarryPlanProductVo vo = new ImportCarryPlanProductVo();
            //赋值
            BeanUtils.copyProperties(product, vo);
            //合同类型,默认其它入库
            vo.setContractType(ContractTypeEnum.OTHER_IN_STOCK.getId());
            //获取已被调用数量
            BigDecimal sum = getQuantityAlreadyOut(product.getProductCode(), product.getSpecificationCode(), product.getPurchaseNo());
            //产品总数
            BigDecimal totalQuantity = new BigDecimal("0");
            if (StringUtil.isNotEmpty(product.getTotalQuantity())) {
                totalQuantity = product.getTotalQuantity();
            }
            //剩余数量
            vo.setReferenceQuantity(totalQuantity.subtract(sum));

            voList.add(vo);
        }

        return voList;
    }

    /**
     * 获取已出数量
     *
     * @param productCode       产品编码
     * @param specificationCode 规格编码
     * @param purchaseNo        采购单号、出运计划号
     * @return 已出数量
     */
    private BigDecimal getQuantityAlreadyOut(String productCode, String specificationCode, String purchaseNo) {
        OtherInStockDetailEntity detailReq = new OtherInStockDetailEntity();
        //产品编码
        detailReq.setProductCode(productCode);
        //规格编码
        detailReq.setSpecificationCode(specificationCode);
        //采购单号(出运计划号)
        detailReq.setPurchaseNo(purchaseNo);
        //获取结果
        List<OtherInStockDetailEntity> detailList = otherInStockDetailService.getOtherInStockDetail(detailReq);
        //已入库总数
        BigDecimal sum = new BigDecimal("0");
        if (!CollectionUtils.isEmpty(detailList)) {
            for (OtherInStockDetailEntity detail : detailList) {
                BigDecimal productNum = new BigDecimal("0");
                if (StringUtil.isNotEmpty(detail.getProductNum())) {
                    productNum = detail.getProductNum();
                }
                sum = sum.add(productNum);
            }
        }
        return sum;
    }


    /**
     * 其它入库新增
     *
     * @param req      新增参数实体
     * @param creator  创建人
     * @param createNo 创建人编码
     * @return 新增结果
     */
    @Transactional(rollbackFor = Exception.class)
    public R add(AddOtherInStockReq req, String creator, String createNo) {
        boolean billNoCheckFlag = (null != req.getId() && req.getBillNo().equals(req.getNewBillNo()));
        if (!billNoCheckFlag) {
            //单号做唯一校验
            boolean billNoFlag = checkRepeatBillNo(req.getBillNo());
            if (!billNoFlag) {
                return R.buildError(ResultStatusEnum.BILL_NO_REPEAT);
            }
        }

        //第一步：主表新增、修改
        Integer id = insert(req, creator, createNo);
        if (null == id) {
            return R.buildError(ResultStatusEnum.SYSTEM_ERROR);
        }

        //第二部：明细新增
        insertDetail(req, id, creator, createNo);

        //第三步：添加附件信息
        boolean flag = addAnnex(req.getAnnexList(), id, creator, createNo);
        if (!flag) {
            LOGGER.info("仓库管理-其它入库-批量新增附件异常");
            return R.buildError(ResultStatusEnum.SYSTEM_ERROR);
        }
        //第四步：删除临时附件信息
        deleteTempAnnex(req.getAnnexList());

        return R.build(ResultStatusEnum.SUCCESS);
    }

    /**
     * 批量处理临时附件信息，将临时附件设置为失效
     *
     * @param annexReqs
     */
    private void deleteTempAnnex(List<AnnexReq> annexReqs) {
        //没有附件
        if (CollectionUtils.isEmpty(annexReqs)) {
            return;
        }
        //存在附件
        for (AnnexReq annex : annexReqs) {
            if (null != annex.getNews()) {
                //旧附件,不用修改
                continue;
            }
            TempAnnexEntity tempAnnex = new TempAnnexEntity();
            //设置临时附件id
            tempAnnex.setId(annex.getId());
            //设置修改时间
            tempAnnex.setUpdateTime(new Date());
            //将附件设置为失效
            tempAnnex.setValid(0);
            tempAnnexService.update(tempAnnex);
        }

    }

    /**
     * 附件新增
     *
     * @param annexReqs  附件信息
     * @param id         入库id
     * @param operator   操作人
     * @param operatorNo 操作人编码
     * @return 是否新增成功(true : 成功 false : 失败)
     */
    private boolean addAnnex(List<AnnexReq> annexReqs, Integer id, String operator, String operatorNo) {
        try {
            //没有附件,将该id关联的所有附件设为无效
            if (CollectionUtils.isEmpty(annexReqs)) {
                AnnexEntity annexReq = new AnnexEntity();
                annexReq.setParentId(id);
                annexReq.setModuleId(ModuleTypeEnum.WAREHOUSE_OTHER_IN_STOCK.getId());
                List<AnnexEntity> annexList = annexService.queryAll(annexReq);
                if (!CollectionUtils.isEmpty(annexList)) {
                    for (AnnexEntity annex : annexList) {
                        AnnexEntity updateAnnex = new AnnexEntity();
                        updateAnnex.setId(annex.getId());
                        //将被删除的附件设为失效
                        updateAnnex.setValid(DataIsValidEnum.INVALID.getId());
                        annexService.update(updateAnnex);
                    }
                }
                return true;
            }
            //存在附件,新增附件信息
            List<AnnexEntity> list = new ArrayList<>();
            //获取旧的附件id集合
            List<Integer> oldIds = new ArrayList<>();
            for (AnnexReq annexReq : annexReqs) {
                if (null != annexReq.getNews()) {
                    //属于旧附件 只取id,不新增
                    oldIds.add(annexReq.getId());
                    continue;
                }
                AnnexEntity annex = new AnnexEntity();
                BeanUtils.copyProperties(annexReq, annex);
                //设置关联模块id
                annex.setModuleId(ModuleTypeEnum.WAREHOUSE_OTHER_IN_STOCK.getId());
                //设置关联模块父id
                annex.setParentId(id);
                //设置上传时间
                annex.setUploadTime(DateUtils.convertStringToDate(annexReq.getUploadTime(), DateUtils.DATE_TIME_PATTERN));
                //设置修改时间
                annex.setUpdateTime(new Date());
                //设置操作人
                annex.setOperator(operator);
                //设置操作人编码
                annex.setOperatorNo(operatorNo);
                //设置数据有效
                annex.setValid(1);

                list.add(annex);
            }
            if (oldIds.size() > 0) {
                //通过调拨id获取修改附件信息
                AnnexEntity annex = new AnnexEntity();
                annex.setModuleId(ModuleTypeEnum.WAREHOUSE_OTHER_IN_STOCK.getId());
                annex.setParentId(id);
                //获取上次附件信息
                List<AnnexEntity> annexList = annexService.queryAll(annex);
                if (!CollectionUtils.isEmpty(annexList)) {
                    //获取上次附件id集合
                    List<Integer> oldAnnexIds = annexList.stream().map(p -> p.getId()).collect(Collectors.toList());
                    //得到被删除的附件id
                    Collection collection = new ArrayList(oldAnnexIds);
                    collection.removeAll(oldIds);
                    if (collection.size() > 0) {
                        Iterator<Integer> it = collection.iterator();
                        while (it.hasNext()) {
                            int detailId = it.next();
                            AnnexEntity annexEntity = new AnnexEntity();
                            annexEntity.setId(detailId);
                            //将被删除的附件设为失效
                            annexEntity.setValid(DataIsValidEnum.INVALID.getId());

                            annexService.update(annexEntity);
                        }
                    }
                }
            }
            if (!CollectionUtils.isEmpty(list)) {
                //附件批量新增
                int res = annexService.batchInsert(list);
                if (res == list.size()) {
                    return true;
                }
            }
            return true;
        } catch (Exception e) {
            throw new RuntimeException();
        }
    }

    /**
     * 明细新增
     *
     * @param req      入参
     * @param id       出库id
     * @param creator  创建人
     * @param createNo 创建人编码
     */
    public void insertDetail(AddOtherInStockReq req, Integer id, String creator, String createNo) {
        if (!CollectionUtils.isEmpty(req.getDetails())) {
            //获取修改明细id集合
            List<Integer> newIds = new ArrayList<>();
            //新增明细集合
            List<OtherInStockDetailEntity> addDetails = new ArrayList<>();
            for (AddOtherInStockDetailReq detailReq : req.getDetails()) {
                //初始化明细对象
                OtherInStockDetailEntity detail = new OtherInStockDetailEntity();
                //赋值
                BeanUtils.copyProperties(detailReq, detail);
                //设置id
                detail.setParentId(id);
                //设置数据有效性(0:无效 1:有效)
                detail.setValid(DataIsValidEnum.VALID.getId());
                //创建时间
                detail.setCreateDate(new Date());

                //库存明细新增
                int stockDetailId = addStockDetail(detailReq, req.getBillNo(), creator, createNo);

                if (null == detailReq.getId()) {
                    //新增

                    //设置明细库存id
                    detail.setStockDetailId(stockDetailId);
                    addDetails.add(detail);
                } else {
                    //修改

                    //获取明细id
                    newIds.add(detailReq.getId());
                    detail.setModifyTime(new Date());
                    otherInStockDetailService.update(detail);
                }

            }

            //处理被删除的入库明细
            handleBeenDeletedTransferDetail(req, id, newIds);

            if (!CollectionUtils.isEmpty(addDetails)) {
                //调用接口保存入库明细
                otherInStockDetailService.addList(addDetails);
            }
        }
    }

    /**
     * 处理被删除的入库明细
     *
     * @param req    入库明细
     * @param id     入库id
     * @param newIds 修改后未被删除的入库明细id集合
     */
    private void handleBeenDeletedTransferDetail(AddOtherInStockReq req, int id, List<Integer> newIds) {
        if (null != req.getId()) {
            //修改-找出被删除的入库明细

            OtherInStockDetailEntity detailReq = new OtherInStockDetailEntity();
            //设置入库id
            detailReq.setParentId(id);
            //查询有效数据
            detailReq.setValid(DataIsValidEnum.VALID.getId());
            //调用接口查询结果
            List<OtherInStockDetailEntity> details = otherInStockDetailService.queryAll(detailReq);
            if (!CollectionUtils.isEmpty(details)) {
                //获取id集合
                List<Integer> oldIds = details.stream().map(p -> p.getId()).collect(Collectors.toList());
                //找出被删除的id
                Collection collection = new ArrayList(oldIds);
                collection.removeAll(newIds);
                if (collection.size() > 0) {
                    //遍历删除被删除的明细
                    Iterator<Integer> ids = collection.iterator();
                    while (ids.hasNext()) {
                        int deletedId = ids.next();
                        OtherInStockDetailEntity detail = new OtherInStockDetailEntity();
                        detail.setId(deletedId);
                        detail.setValid(DataIsValidEnum.INVALID.getId());
                        //将删除的出库明细设为无效
                        otherInStockDetailService.update(detail);
                    }
                }
            }
        }
    }

    /**
     * 新增库存明细
     *
     * @param detailReq 入库明细
     * @param billNo    单号
     * @param creator   创建人
     * @param createNo  创建人编码
     */
    private int addStockDetail(AddOtherInStockDetailReq detailReq, String billNo, String creator, String createNo) {
        //初始化库存明细对象
        StockDetailEntity stockDetail = new StockDetailEntity();
        //赋值
        BeanUtils.copyProperties(detailReq, stockDetail);
        //设置标题
        stockDetail.setTitle(DataSourceTitleEnum.OTHER_IN_STOCK.getDesc());
        //设置单据编号
        stockDetail.setInvoiceNumber(billNo);
        //设置单价
        stockDetail.setUnitPrice(detailReq.getInstoreUnitPrice());
        //设置数量
        stockDetail.setQuantity(detailReq.getProductNum());
        //设置模块id
        stockDetail.setModuleId(ModuleTypeEnum.WAREHOUSE_PLAN_IN_STOCK.getId());
        //设置创建人
        stockDetail.setInStorePerson(creator);
        //设置创建人编码
        stockDetail.setInStoreCode(createNo);
        //设置操作人
        stockDetail.setOperator(creator);
        //设置操作人编码
        stockDetail.setOperationCode(createNo);
        if (null == detailReq.getId()) {
            //新增

            //设置创建时间
            stockDetail.setCreateDate(new Date());
            //设置有效性
            stockDetail.setValid(DataIsValidEnum.VALID.getId());
            stockDetailService.insert(stockDetail);

        } else {
            //修改

            stockDetail.setId(detailReq.getStockDetailId());
            stockDetailService.update(stockDetail);
        }

        return stockDetail.getId();
    }

    /**
     * 其它入库新增、修改
     *
     * @param req      参数实体
     * @param creator  创建人
     * @param createNo 创建人编码
     * @return 新增、修改结果
     */
    private Integer insert(AddOtherInStockReq req, String creator, String createNo) {
        //初始化对象
        OtherInStockEntity planInStore = new OtherInStockEntity();
        //赋值
        BeanUtils.copyProperties(req, planInStore);
        //设置创建人
        planInStore.setOperator(creator);
        //设置创建人编码
        planInStore.setOperationNo(createNo);
        //设置状态,默认为草稿箱
        planInStore.setStatus(OperationStatusEnum.DRAFT_BOX.getId());

        if (null == req.getId()) {
            //新增
            //创建日期
            planInStore.setCreateDate(new Date());
            //设置有效性
            planInStore.setValid(DataIsValidEnum.VALID.getId());
            //调用接口新增
            otherInStockService.insert(planInStore);
        } else {
            //修改
            //修改时间
            planInStore.setModifyTime(new Date());
            otherInStockService.update(planInStore);
        }
        return planInStore.getId();
    }


    /**
     * 校验单号是否存在
     *
     * @param billNo 单号
     * @return true:不重复 false:重复
     */
    private boolean checkRepeatBillNo(String billNo) {
        OtherInStockEntity req = new OtherInStockEntity();
        req.setBillNo(billNo);
        List<OtherInStockEntity> list = otherInStockService.queryAll(req);
        if (CollectionUtils.isEmpty(list)) {
            return true;
        }
        return false;
    }


    /**
     * 获取详情
     *
     * @param id 入库id
     * @return 详情
     */
    public OtherInStockInfoVo getDetailInfo(Integer id) {
        //初始化回参实体
        OtherInStockInfoVo vo = new OtherInStockInfoVo();
        if (null == id) {
            return vo;
        }

        //第一步：获取主表信息
        OtherInStockEntity planInStore = otherInStockService.queryById(id);
        if (null == planInStore || null == planInStore.getId()) {
            return vo;
        }
        //赋值
        BeanUtils.copyProperties(planInStore, vo);
        //设置创建时间
        vo.setCreateDate(DateUtils.format(planInStore.getCreateDate()));

        //第二步：获取对应产品信息
        OtherInStockDetailEntity detailReq = new OtherInStockDetailEntity();
        //设置入库id
        detailReq.setParentId(id);
        //设置数据为有效
        detailReq.setValid(DataIsValidEnum.VALID.getId());
        List<OtherInStockDetailEntity> details = otherInStockDetailService.queryAll(detailReq);

        if (!CollectionUtils.isEmpty(details)) {
            List<OtherInStockDetailInfoVo> productVos = details.stream().map(p -> {
                OtherInStockDetailInfoVo productVo = new OtherInStockDetailInfoVo();
                //赋值
                BeanUtils.copyProperties(p, productVo);
                return productVo;
            }).collect(Collectors.toList());

            vo.setDetailList(productVos);
        }

        //第三步：获取附件信息
        AnnexEntity annex = new AnnexEntity();
        annex.setModuleId(ModuleTypeEnum.WAREHOUSE_OTHER_IN_STOCK.getId());
        annex.setParentId(id);
        //设置数据有效
        annex.setValid(DataIsValidEnum.VALID.getId());
        List<AnnexEntity> annexList = annexService.queryAll(annex);
        if (!CollectionUtils.isEmpty(annexList)) {
            List<AnnexVo> annexVos = annexList.stream().map(p -> {
                AnnexVo annexVo = new AnnexVo();
                //赋值
                BeanUtils.copyProperties(p, annexVo);
                //上传时间转换
                annexVo.setUploadTime(DateUtils.format(p.getUploadTime(), DateUtils.DATE_TIME_PATTERN));
                //设置附件为旧附件,用以区分修改时附件状态
                annexVo.setNews(0);

                return annexVo;
            }).collect(Collectors.toList());

            vo.setAnnexList(annexVos);
        }
        return vo;
    }


    /**
     * 删除
     *
     * @param req 参数对象
     */
    public void delete(OperationReq req) {
        if (null == req.getId() || null == req.getStatus()) {
            return;
        }
        OtherInStockEntity infoReq = new OtherInStockEntity();
        infoReq.setId(req.getId());
        infoReq.setModifyTime(new Date());
        if (req.getStatus().equals(OperationStatusEnum.DRAFT_BOX.getId())) {
            //草稿箱删除,数位改为垃圾箱
            infoReq.setStatus(OperationStatusEnum.TRASH_CAN.getId());
            otherInStockService.update(infoReq);
            return;
        } else {
            //垃圾箱删除,将主数据设为无效
            infoReq.setValid(DataIsValidEnum.INVALID.getId());
            otherInStockService.update(infoReq);
        }
        //获取对应明细数据
        OtherInStockDetailEntity detailEntity = new OtherInStockDetailEntity();
        detailEntity.setParentId(req.getId());
        detailEntity.setValid(DataIsValidEnum.VALID.getId());

        List<OtherInStockDetailEntity> detailList = otherInStockDetailService.queryAll(detailEntity);
        if (CollectionUtils.isEmpty(detailList)) {
            return;
        }
        //将所有对应有效的明细数据设为无效
        for (OtherInStockDetailEntity detail : detailList) {
            OtherInStockDetailEntity detailReq = new OtherInStockDetailEntity();
            detailReq.setId(detail.getId());
            detailReq.setModifyTime(new Date());
            detailReq.setValid(DataIsValidEnum.INVALID.getId());

            otherInStockDetailService.update(detailReq);
        }

        //获取对应所有附件
        AnnexEntity annex = new AnnexEntity();
        annex.setModuleId(ModuleTypeEnum.WAREHOUSE_OTHER_IN_STOCK.getId());
        annex.setParentId(req.getId());
        annex.setValid(DataIsValidEnum.VALID.getId());
        List<AnnexEntity> annexList = annexService.queryAll(annex);
        if (CollectionUtils.isEmpty(annexList)) {
            return;
        }
        //删除所有对应的有效的附件
        for (AnnexEntity annexData : annexList) {
            AnnexEntity annexReq = new AnnexEntity();
            annexReq.setId(annexData.getId());
            annexReq.setUpdateTime(new Date());
            annexReq.setValid(DataIsValidEnum.INVALID.getId());

            annexService.update(annexReq);
        }
    }


    /**
     * 收款首页-箱体操作
     *
     * @param req
     */
    public R operation(OperationReq req, String msn) {
        if (null == req.getId() || null == req.getOperation() || StringUtils.isBlank(req.getBillNo())) {
            return R.buildError(ResultStatusEnum.SYSTEM_ERROR);
        }
        OtherInStockEntity offerEntity = new OtherInStockEntity();
        //设置修改主键
        offerEntity.setId(req.getId());
        //修改时间
        offerEntity.setModifyTime(new Date());

        switch (req.getOperation()) {
            case 1:
                if (StringUtils.isNotEmpty(msn) && "是".equals(msn)) {
                    //提交审批后,状态为已批箱
                    offerEntity.setStatus(OperationStatusEnum.APPROVED_BOX.getId());
                    //数据同时进入库存
                    addStockInfo(req.getId(), req.getBillNo());
                } else {
                    //提交审批后,状态为待批箱
                    offerEntity.setStatus(OperationStatusEnum.PENDING_BOX.getId());
                }
                break;
            case 2:
                //审批通过,状态设为已批箱
                offerEntity.setStatus(OperationStatusEnum.APPROVED_BOX.getId());
                //数据同时进入库存
                addStockInfo(req.getId(), req.getBillNo());
                break;
            case 3:
                //审批退回
                //校验是否可以回退数据 true:是 false:否
                boolean flag = checkDataIsRollBack(req.getId());
                if (flag) {
                    //状态设为草稿箱
                    offerEntity.setStatus(OperationStatusEnum.DRAFT_BOX.getId());
                    //仓库数据设为无效
                    deleteStockInfo(req.getId());
                } else {
                    //审批退回失败,存在已被调用的产品
                    return R.buildError(ResultStatusEnum.APPROVAL_RETURNED_FAILED);
                }
                break;
            case 4:
                //将状态设为完成
                offerEntity.setStatus(OperationStatusEnum.COMPLETION_BOX.getId());
                break;
            case 5:
                //点击还原，将状态改为草稿箱
                offerEntity.setStatus(OperationStatusEnum.DRAFT_BOX.getId());
                break;
        }
        //调用接口修改
        otherInStockService.update(offerEntity);
        return R.buildError(ResultStatusEnum.SUCCESS);
    }

    /**
     * 审批通过后，库存数据新增
     *
     * @param id     主键id
     * @param billNo 单号
     */
    private void addStockInfo(Integer id, String billNo) {
        //获取主信息数据
        OtherInStockEntity otherInStock = otherInStockService.queryById(id);
        //获取明细信息
        OtherInStockDetailEntity detailReq = new OtherInStockDetailEntity();
        //设置父id
        detailReq.setParentId(id);
        //设置数据有效
        detailReq.setValid(DataIsValidEnum.VALID.getId());
        //获取产品信息
        List<OtherInStockDetailEntity> detailList = otherInStockDetailService.queryAll(detailReq);
        if (CollectionUtils.isEmpty(detailList)) {
            return;
        }
        for (OtherInStockDetailEntity detail : detailList) {
            StockEntity stockReq = new StockEntity();
            //赋值
            BeanUtils.copyProperties(detail, stockReq);
            //批次号:入库单号-采购单号
            String letNo = billNo + "-" + detail.getPurchaseNo();
            stockReq.setLotNo(letNo);
            //入库单号
            stockReq.setInStoreBillNo(billNo);
            //实际数量
            stockReq.setRealQuantity(detail.getProductNum());
            //实际可用数量
            stockReq.setRealAvailableQuantity(detail.getProductNum());
            //可申请数量
            stockReq.setCanApplyQuantity(detail.getProductNum());
            //调拨申请数量(默认为零)
            stockReq.setTransferApplyQuantity(new BigDecimal("0"));
            //出库申请数量(默认为零)
            stockReq.setOutWarehouseApply(new BigDecimal("0"));
            //入库日期
            stockReq.setInStoreDate(new Date());
            //数据有效
            stockReq.setValid(DataIsValidEnum.VALID.getId());
            //备注
            stockReq.setMemo(otherInStock.getMemo());
            //库存新增
            stockService.insert(stockReq);
            //修改其它入库产品信息
            OtherInStockDetailEntity detailEntity = new OtherInStockDetailEntity();
            //主键id
            detailEntity.setId(detail.getId());
            //新增库存id
            detailEntity.setStockId(stockReq.getId());
            otherInStockDetailService.update(detailEntity);
        }
    }

    /**
     * 审批退回后,删除对应仓库数据
     *
     * @param id 主键id
     */
    private void deleteStockInfo(Integer id) {
        OtherInStockDetailEntity detailReq = new OtherInStockDetailEntity();
        //设置父id
        detailReq.setParentId(id);
        //设置数据有效
        detailReq.setValid(DataIsValidEnum.VALID.getId());
        //获取报价产品信息
        List<OtherInStockDetailEntity> detailList = otherInStockDetailService.queryAll(detailReq);
        if (CollectionUtils.isEmpty(detailList)) {
            return;
        }
        for (OtherInStockDetailEntity detail : detailList) {
            StockEntity stockReq = new StockEntity();
            //设置修改id
            stockReq.setId(detail.getStockId());
            //数据设为无效
            stockReq.setValid(DataIsValidEnum.INVALID.getId());
            //修改库存
            stockService.update(stockReq);
        }
    }

    /**
     * 校验是否可以回退数据 true:是 false:否
     *
     * @param id 主键id
     * @return 是否可以回退数据
     */
    private Boolean checkDataIsRollBack(Integer id) {
        OtherInStockDetailEntity detailReq = new OtherInStockDetailEntity();
        //设置父id
        detailReq.setParentId(id);
        //设置数据有效
        detailReq.setValid(DataIsValidEnum.VALID.getId());
        //获取报价产品信息
        List<OtherInStockDetailEntity> detailList = otherInStockDetailService.queryAll(detailReq);
        if (CollectionUtils.isEmpty(detailList)) {
            return true;
        }
        for (OtherInStockDetailEntity detail : detailList) {
            StockEntity stockReq = new StockEntity();
            //产品编码
            stockReq.setProductCode(detail.getProductCode());
            //规格编码
            stockReq.setSpecificationCode(detail.getSpecificationCode());
            //业务类型:其它入库
            stockReq.setContractType(detail.getContractType());
            //数据有效
            stockReq.setValid(DataIsValidEnum.VALID.getId());
            //查询库存
            List<StockEntity> stockList = stockService.queryAll(stockReq);
            if (CollectionUtils.isEmpty(stockList)) {
                continue;
            }
            for (StockEntity stock : stockList) {
                if (!StringUtils.isBlank(stock.getContractNo())) {
                    //合同号不为空,证明该产品已被调用,不能退回
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 其它入库产品列表统计-分页
     *
     * @param req 查询条件
     * @return 其它出库产品列表统计
     */
    public PageInfo<OtherInStockProductStatisticsVo> statisticsProductInfo(sellOutStockStatistics1Req req) {
        //初始化回参实体
        List<OtherInStockProductStatisticsVo> voList = new ArrayList<>();
        List<OtherInStockProductStatisticsRsp> statistics = otherInStockDetailService.statisticsProductInfo(req);
        if (CollectionUtils.isEmpty(statistics)) {
            PageInfo pageInfo = new PageInfo();
            pageInfo.setList(voList);
            return pageInfo;
        }
        //获取分页信息
        PageInfo pageInfo = new PageInfo(statistics);
        for (OtherInStockProductStatisticsRsp info : statistics) {
            //初始化回参对象
            OtherInStockProductStatisticsVo vo = new OtherInStockProductStatisticsVo();
            //赋值
            BeanUtils.copyProperties(info, vo);
            //创建时间
            vo.setCreateDate(DateUtils.format(info.getCreateDate()));

            voList.add(vo);
        }
        pageInfo.setList(voList);
        return pageInfo;
    }
    /**
     * 获取String类型不为空数据
     * @param value 目标数据
     * @return 不为空数据
     */
    private String getNotNullOfStringInfo(String value){
        if(StringUtils.isEmpty(value)){
            return "";
        }else {
            return value;
        }
    }

    /**
     * 获取BigDecimal类型不为空的数据
     * @param value 目标数据
     * @return 不为空数据
     */
    private BigDecimal getNotNullOfBigDecimalInfo(BigDecimal value){
        if(StringUtil.isNotEmpty(value)){
            return value;
        }else {
            return new BigDecimal("0");
        }
    }
    /**
     * 其它入库产品列表统计-导出
     * @param req
     * @return
     */
    public JSONObject statisticsProductInfoExport(sellOutStockStatistics1Req req){
        List<OtherInStockProductStatisticsVo> voList = new ArrayList<>();
        List<OtherInStockProductStatisticsRsp> statistics = otherInStockDetailService.statisticsProductInfo(req);
        for (OtherInStockProductStatisticsRsp info : statistics) {
            //初始化回参对象
            OtherInStockProductStatisticsVo vo = new OtherInStockProductStatisticsVo();
            //赋值
            BeanUtils.copyProperties(info, vo);
            //创建时间
            vo.setCreateDate(DateUtils.format(info.getCreateDate()));

            voList.add(vo);
        }

        JSONObject obj = new JSONObject();
        //获取excel的title信息
        JSONArray titleList = getTitleProductInfo();
        JSONArray data = new JSONArray();
        data.add(titleList);
        if(CollectionUtils.isEmpty(voList)){
            obj.put("data", data);
            return obj;
        }
        excelProductInfoExport(data,voList);
        obj.put("data", data);
        return obj;
    }
    public JSONArray getTitleProductInfo(){
        JSONArray obj=new JSONArray();
        obj.add("序号");
        obj.add("入库单号");
        obj.add("入库日期");
        obj.add("入库人");
        obj.add("仓库名称");
        obj.add("产品编码");
        obj.add("规格编码");
        obj.add("规格说明");
        obj.add("客户货号");
        obj.add("采购单号");
        obj.add("供应商名称");
        obj.add("产品单位");
        obj.add("产品数量");
        obj.add("托盘入数");
        obj.add("总托盘");
        obj.add("中文名称");
        obj.add("英文名称");
        obj.add("中文描述");
        obj.add("英文描述");
        obj.add("备注");
        return obj;
    }
    public void excelProductInfoExport(JSONArray data,List<OtherInStockProductStatisticsVo> list ){
        //产品数量
        BigDecimal productNum = new BigDecimal("0");
        //托盘入数
        BigDecimal trayNumber = new BigDecimal("0");
        //总托盘
        BigDecimal totalTray = new BigDecimal("0");
        Integer i=0;
        for (OtherInStockProductStatisticsVo vo: list) {
            JSONArray infoList = new JSONArray();
            infoList.add(++i);
            infoList.add(getNotNullOfStringInfo(vo.getBillNo()));
            infoList.add(getNotNullOfStringInfo(vo.getCreateDate()));
            infoList.add(getNotNullOfStringInfo(vo.getPerson()));
            infoList.add(getNotNullOfStringInfo(vo.getWarehouseName()));
            infoList.add(getNotNullOfStringInfo(vo.getProductCode()));
            infoList.add(getNotNullOfStringInfo(vo.getSpecificationCode()));
            infoList.add(getNotNullOfStringInfo(vo.getSpecificationExplanation()));
            infoList.add(getNotNullOfStringInfo(vo.getClientProductNo()));
            infoList.add(getNotNullOfStringInfo(vo.getPurchaseNo()));
            infoList.add(getNotNullOfStringInfo(vo.getSupplierName()));
            infoList.add(getNotNullOfStringInfo(vo.getProductUnit()));

            infoList.add(getNotNullOfBigDecimalInfo(vo.getProductNum()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getTrayNumber()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getTotalTray()));
            infoList.add(getNotNullOfStringInfo(vo.getProductCname()));
            infoList.add(getNotNullOfStringInfo(vo.getProductEname()));
            infoList.add(getNotNullOfStringInfo(vo.getProductCdesc()));
            infoList.add(getNotNullOfStringInfo(vo.getProductEdesc()));
            infoList.add(getNotNullOfStringInfo(vo.getMemo()));
            if(StringUtil.isNotEmpty(vo.getProductNum())){
                productNum = productNum.add(vo.getProductNum());
            }
            if(StringUtil.isNotEmpty(vo.getTrayNumber())){
                trayNumber = trayNumber.add(vo.getTrayNumber());
            }
            if(StringUtil.isNotEmpty(vo.getTotalTray())){
                totalTray = totalTray.add(vo.getTotalTray());
            }
            data.add(infoList);
        }
        //合计
        JSONArray infoList = new JSONArray();
        infoList.add("合计");
        infoList.add("");
        infoList.add("");
        infoList.add("");
        infoList.add("");
        infoList.add("");
        infoList.add("");
        infoList.add("");
        infoList.add("");
        infoList.add("");
        infoList.add("");
        infoList.add("");
        infoList.add(productNum);
        infoList.add(trayNumber);
        infoList.add(totalTray);
        infoList.add("");
        infoList.add("");
        infoList.add("");
        infoList.add("");
        infoList.add("");
        data.add(infoList);
    }


}
